package com.fs.core.security.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;

/**
 * json请求转换包装
 * 
 * @author ghz
 *
 */
public class JsonRequestWrapper extends HttpServletRequestWrapper implements SecurityConstant {

	/**
	 * 请求加密
	 */
	private static final String SSL_LINK = "SSL_LINK";

	/**
	 * 数据
	 */
	private static final String SSL_DATA = "SSL_PA1";

	/**
	 * 公钥
	 */
	private static final String SSL_KEY = "SSL_PA3";

	/**
	 * 完整性保护算法
	 */
	private static final String SSL_PROTECT = "SSL_PA2";

	/**
	 * 请求类型
	 */
	private static final String REQUEST_TYPE = "REQUEST_TYPE";

	/**
	 * 缓存请求体
	 */
	private final String body;


	/** 日志对象 */
	private static Logger log = LoggerFactory.getLogger(DecryptionHelper.class);

	/**
	 * 包装对象
	 * 
	 * @param request
	 * @throws IOException
	 */
	@SuppressWarnings("unchecked")
	public JsonRequestWrapper(HttpServletRequest request) throws Exception {
		super(request);
		String utf8DecodeData = getBody(request);
		// 设置返回数据
		body = utf8DecodeData;
		log.info("解密获取的json格式为:"+body);
	}

	/**
	 * 获取请求body
	 * @param request 请求对象
	 * @return
	 * @throws IOException
	 */
	private String getBody(HttpServletRequest request) throws Exception {
		/* 首先进行解密处理，将body转换成为map对象 */
		StringBuilder sb = new StringBuilder();
		String line;
		BufferedReader reader = request.getReader();
		char[] buff = new char[1024];
		int len;
		while ((len = reader.read(buff)) != -1) {
			sb.append(buff, 0, len);
		}

		/* 解密结果获取原始数据*/
		Map<String, Object> map = JsonXMLUtil.json2map(sb.toString());
		String allData = "";
		try {
//			allData = DecryptionHelper.getDecryptData(map.get(SSL_DATA).toString(), map.get(SSL_KEY).toString());
			allData = DecryptionHelper.getDecryptData(map.get(SSL_DATA).toString(),"");
		} catch (Exception e) {
			String message = "数据解析失败。";
			log.error(message, e);
			throw new Exception(message,e);
		}

		/* 继续解析，获取原始数据以及加密比较数据进行数据比较 */
		map = JsonXMLUtil.json2map(allData);
		ThreadLocalUtils.setObjectToThreadLocal(SecurityConstant.SSL_DECODE_DATA, map);
		// 重新进行编码
		String decodeData = map.get(SSL_DATA).toString();
		String utf8DecodeData = decodeData;
		try {
			utf8DecodeData = new String(decodeData.getBytes(), "UTF-8");
		} catch (Exception e) {
			String message = "SSL_DATA数据校验完整性失败。";
			log.error(message, e);
			throw new Exception(message,e);
		}
		String protect = map.get(SSL_PROTECT).toString();
		if (decodeData != null && DecryptionHelper.validate(utf8DecodeData, protect)) {
			String message = "校验数据完整性成功";
			log.info(message);
		} else {
			String message = "校验数据完整性失败";
			log.info(message);
			throw new Exception(message);
		}
		return utf8DecodeData;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.ServletRequestWrapper#getInputStream()
	 */
	@Override
	public ServletInputStream getInputStream() throws IOException {
		final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes());
		return new ServletInputStream() {
			@Override
			public int read() throws IOException {
				return bais.read();
			}

			@Override
			public boolean isFinished() {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public boolean isReady() {
				// TODO Auto-generated method stub
				return false;
			}

			@Override
			public void setReadListener(ReadListener readListener) {
				// TODO Auto-generated method stub

			}
		};
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.servlet.ServletRequestWrapper#getReader()
	 */
	@Override
	public BufferedReader getReader() throws IOException {
		return new BufferedReader(new InputStreamReader(this.getInputStream()));
	}

}
